[System.CodeDom.Compiler.GeneratedCode("NSwag", "{{ ToolchainVersion }}")]
{{ ClientClassAccessModifier }} partial class {{ Class }} {% if HasBaseType %}: {% endif %}{% if HasBaseClass %}{{ BaseClass }}{% if GenerateClientInterfaces %}, {% endif %}{% endif %}{% if GenerateClientInterfaces %}I{{ Class }}{% endif %}
{
{% if UseBaseUrl and GenerateBaseUrlProperty -%}
    private string _baseUrl = "{{ BaseUrl }}";
{% endif -%}
{% if InjectHttpClient -%}
    private {{ HttpClientType }} _httpClient;
{% endif -%}
{% if UseRequestAndResponseSerializationSettings -%}
    private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _requestSettings;
    private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _responseSettings;
{% else -%}
    private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
{% endif -%}

{% if HasConfigurationClass -%}
    public {{ Class }}({{ ConfigurationClass }} configuration{% if InjectHttpClient %}, {{ HttpClientType }} httpClient{% endif %}) : base(configuration)
    {
{%     if InjectHttpClient -%}
        _httpClient = httpClient; 
{%     endif -%}
{% elseif UseBaseUrl and HasBaseUrl == false -%}
    public {{ Class }}(string baseUrl{% if InjectHttpClient -%}, {{ HttpClientType }} httpClient{% endif %})
    {
        BaseUrl = baseUrl; 
{%     if InjectHttpClient -%}
        _httpClient = httpClient; 
{%     endif -%}
{% elseif InjectHttpClient -%}
    public {{ Class }}({{ HttpClientType }} httpClient)
    {
        _httpClient = httpClient; 
{% else -%}
    public {{ Class }}()
    {
{% endif -%}
{% if UseRequestAndResponseSerializationSettings -%}
        _requestSettings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(() => CreateSerializerSettings(true));
        _responseSettings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(() => CreateSerializerSettings(false));
{% else -%}
        _settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
{% endif -%}
        {% template Client.Class.Constructor %}
    }

    private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings({% if UseRequestAndResponseSerializationSettings %}bool isRequest{% endif %})
    {
        var settings = {{ JsonSerializerParameterCode }};
{% if SerializeTypeInformation -%}
        settings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;
{% endif -%}
        UpdateJsonSerializerSettings(settings{% if UseRequestAndResponseSerializationSettings %}, isRequest{% endif %});
        return settings;
    }

{% if UseBaseUrl and GenerateBaseUrlProperty -%}
    public string BaseUrl 
    {
        get { return _baseUrl; }
        set { _baseUrl = value; }
    }

{% endif -%}
{% if ExposeJsonSerializerSettings %}
{%     assign serializerSettingsAccessModifier = "public" -%}
{% else -%}
{%     assign serializerSettingsAccessModifier = "protected" -%}
{% endif -%}
{% if UseRequestAndResponseSerializationSettings -%}
    {{ serializerSettingsAccessModifier }} Newtonsoft.Json.JsonSerializerSettings RequestJsonSerializerSettings { get { return _requestSettings.Value; } }
    {{ serializerSettingsAccessModifier }} Newtonsoft.Json.JsonSerializerSettings ResponseJsonSerializerSettings { get { return _responseSettings.Value; } }
{% else -%}
    {{ serializerSettingsAccessModifier }} Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } }
{% endif -%}

{% if GenerateUpdateJsonSerializerSettingsMethod -%}
{%     if UseRequestAndResponseSerializationSettings -%}
    partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings, bool isRequest);
{%     else -%}
    partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
{%     endif -%}
{% endif -%}
    partial void PrepareRequest({{ HttpClientType }} client, System.Net.Http.HttpRequestMessage request, string url);
    partial void PrepareRequest({{ HttpClientType }} client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
    partial void ProcessResponse({{ HttpClientType }} client, System.Net.Http.HttpResponseMessage response);

{% for operation in Operations -%}
{%     if GenerateOptionalParameters == false -%}
    {% template Client.Method.Documentation %}
    {% template Client.Method.Annotations %}
    {{ operation.MethodAccessModifier }} {{ operation.ResultType }} {{ operation.ActualOperationName }}Async({% for parameter in operation.Parameters %}{{ parameter.Type }} {{ parameter.VariableName }}{% if GenerateOptionalParameters and parameter.IsOptional %} = null{% endif %}{% if parameter.IsLast == false %}, {% endif %}{% endfor %})
    {
        return {{ operation.ActualOperationName }}Async({% for parameter in operation.Parameters %}{{ parameter.VariableName }}, {% endfor %}System.Threading.CancellationToken.None);
    }

{%     endif -%}
{%     if GenerateSyncMethods -%}
    {% template Client.Method.Documentation %}
    {% template Client.Method.Annotations %}
    {{ operation.MethodAccessModifier }} {{ operation.SyncResultType }} {{ operation.ActualOperationName }}({% for parameter in operation.Parameters %}{{ parameter.Type }} {{ parameter.VariableName }}{% if GenerateOptionalParameters and parameter.IsOptional %} = null{% endif %}{% if parameter.IsLast == false %}, {% endif %}{% endfor %})
    {
        {% if operation.HasResult or operation.WrapResponse %}return {% endif %}System.Threading.Tasks.Task.Run(async () => await {{ operation.ActualOperationName }}Async({% for parameter in operation.Parameters %}{{ parameter.VariableName }}, {% endfor %}System.Threading.CancellationToken.None)).GetAwaiter().GetResult();
    }

{%     endif -%}
    /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
    {% template Client.Method.Documentation %}
    {% template Client.Method.Annotations %}
    {{ operation.MethodAccessModifier }} async {{ operation.ResultType }} {{ operation.ActualOperationName }}Async({% for parameter in operation.Parameters %}{{ parameter.Type }} {{ parameter.VariableName }}{% if GenerateOptionalParameters and parameter.IsOptional %} = null{% endif %}, {% endfor %}System.Threading.CancellationToken cancellationToken{% if GenerateOptionalParameters %} = default(System.Threading.CancellationToken){% endif %})
    {
{%     for parameter in operation.PathParameters -%}
{%         if parameter.IsNullable == false and parameter.IsRequired -%}
        if ({{ parameter.VariableName }} == null)
            throw new System.ArgumentNullException("{{ parameter.VariableName }}");

{%         endif -%}
{%     endfor -%}
{%     for parameter in operation.QueryParameters -%}
{%         if parameter.IsNullable == false and parameter.IsRequired -%}
        if ({{ parameter.VariableName }} == null)
            throw new System.ArgumentNullException("{{ parameter.VariableName }}");

{%         endif -%}
{%     endfor -%}
{%     if operation.HasContent and operation.ContentParameter.IsRequired -%}
        if ({{ operation.ContentParameter.VariableName }} == null)
            throw new System.ArgumentNullException("{{ operation.ContentParameter.VariableName }}");

{%     endif -%}
        var urlBuilder_ = new System.Text.StringBuilder();
        urlBuilder_.Append({% if UseBaseUrl %}BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/{% else %}"{% endif %}{{ operation.Path }}{% if operation.HasQueryParameters %}?{% endif %}");
{%     for parameter in operation.PathParameters -%}
{%         if parameter.IsOptional -%}
        if ({{ parameter.VariableName }} != null)
            {% template Client.Class.PathParameter %}
        else
            urlBuilder_.Replace("/{{ "{" }}{{ parameter.Name }}}", string.Empty);
{%         else -%}
        {% template Client.Class.PathParameter %}
{%         endif -%}
{%     endfor -%}
{%     for parameter in operation.QueryParameters -%}
{%         if parameter.IsOptional -%}
        if ({{ parameter.VariableName }} != null) 
        {
            {% template Client.Class.QueryParameter %}
        }
{%         else -%}
        {% template Client.Class.QueryParameter %}
{%         endif -%}
{%     endfor -%}
{%     if operation.HasQueryParameters -%}
        urlBuilder_.Length--;
{%     endif -%}

{%     if InjectHttpClient -%}
        var client_ = _httpClient;
{%     elseif UseHttpClientCreationMethod -%}
        var client_ = await CreateHttpClientAsync(cancellationToken).ConfigureAwait(false);
{%     else -%}
        var client_ = new {{ HttpClientType }}();
{%     endif -%}
        try
        {
{%     if UseHttpRequestMessageCreationMethod -%}
            using (var request_ = await CreateHttpRequestMessageAsync(cancellationToken).ConfigureAwait(false))
{%     else -%}
            using (var request_ = new System.Net.Http.HttpRequestMessage())
{%     endif -%}
            {
{%     for parameter in operation.HeaderParameters -%}
{%         if parameter.IsRequired -%}
                if ({{ parameter.VariableName }} == null)
                    throw new System.ArgumentNullException("{{ parameter.VariableName }}");
                {% template Client.Class.HeaderParameter %}
{%         else -%}
                if ({{ parameter.VariableName }} != null)
                    {% template Client.Class.HeaderParameter %}
{%         endif -%}
{%     endfor -%}
{%     if operation.HasContent -%}
{%         if operation.HasBinaryBodyParameter -%}
                var content_ = new System.Net.Http.StreamContent({{ operation.ContentParameter.VariableName }});
{%         elseif operation.HasXmlBodyParameter -%}
                var content_ = new System.Net.Http.StringContent({{ operation.ContentParameter.VariableName }});
{%         else -%}
                var content_ = new System.Net.Http.StringContent(Newtonsoft.Json.JsonConvert.SerializeObject({{ operation.ContentParameter.VariableName }}, {% if SerializeTypeInformation %}typeof({{ operation.ContentParameter.Type }}), {% endif %}{% if UseRequestAndResponseSerializationSettings %}_requestSettings{% else %}_settings{% endif %}.Value));
{%         endif -%}
                content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("{{ operation.Consumes }}");
                request_.Content = content_;
{%     else -%}
{%         if operation.HasFormParameters -%}
{%             if operation.ConsumesFormUrlEncoded -%}
                var keyValues_ = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, string>>();
{%                 for parameter in operation.FormParameters -%}
{%                     if parameter.IsNullable -%}
                if ({{ parameter.VariableName }} != null)
{%                     else -%}
                if ({{ parameter.VariableName }} == null)
                    throw new System.ArgumentNullException("{{ parameter.VariableName }}");
                else
{%                     endif -%}
                    keyValues_.Add(new System.Collections.Generic.KeyValuePair<string, string>("{{ parameter.Name }}", ConvertToString({{ parameter.VariableName }}, System.Globalization.CultureInfo.InvariantCulture)));
{%                 endfor -%}
                request_.Content = new System.Net.Http.FormUrlEncodedContent(keyValues_);
{%             else -%}
                var boundary_ = System.Guid.NewGuid().ToString();
                var content_ = new System.Net.Http.MultipartFormDataContent(boundary_);
                content_.Headers.Remove("Content-Type");
                content_.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary_);
{%                 for parameter in operation.FormParameters -%}
{%                     if parameter.IsNullable -%}
                if ({{ parameter.VariableName }} != null)
{%                     else -%}
                if ({{ parameter.VariableName }} == null)
                    throw new System.ArgumentNullException("{{ parameter.VariableName }}");
                else
{%                     endif -%}
                {
{%                     if parameter.IsFile -%}
{%                         if parameter.IsArray -%}
                    foreach (var item_ in {{ parameter.VariableName }})
                    {
                        var content_{{ parameter.VariableName }}_ = new System.Net.Http.StreamContent(item_.Data);
                        if (!string.IsNullOrEmpty(item_.ContentType))
                            content_{{ parameter.VariableName }}_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(item_.ContentType);
                        content_.Add(content_{{ parameter.VariableName }}_, "{{ parameter.Name }}", item_.FileName ?? "{{ parameter.Name }}");
                    }
{%                         else -%}
                    var content_{{ parameter.VariableName }}_ = new System.Net.Http.StreamContent({{ parameter.VariableName }}.Data);
                    if (!string.IsNullOrEmpty({{ parameter.VariableName }}.ContentType))
                        content_{{ parameter.VariableName }}_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse({{ parameter.VariableName }}.ContentType);
                    content_.Add(content_{{ parameter.VariableName }}_, "{{ parameter.Name }}", {{ parameter.VariableName }}.FileName ?? "{{ parameter.Name }}");
{%                         endif -%}
{%                     else -%}
                    content_.Add(new System.Net.Http.StringContent(ConvertToString({{ parameter.VariableName }}, System.Globalization.CultureInfo.InvariantCulture)), "{{ parameter.Name }}");
{%                     endif -%}
                }
{%                 endfor -%}
                request_.Content = content_;
{%             endif -%}
{%         elseif operation.IsGetOrDeleteOrHead == false -%}
                request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "{{ operation.Produces }}");
{%         endif -%}
{%     endif -%}
                request_.Method = new System.Net.Http.HttpMethod("{{ operation.HttpMethodUpper | upcase }}");
{%     if operation.HasResultType and operation.HasAcceptHeaderParameterParameter == false -%}
                request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("{{ operation.Produces }}"));
{%     endif -%}

                PrepareRequest(client_, request_, urlBuilder_);
                var url_ = urlBuilder_.ToString();
                request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
                PrepareRequest(client_, request_, url_);

                {% template Client.Class.BeforeSend %}
                var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
                try
                {
                    var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
                    if (response_.Content != null && response_.Content.Headers != null)
                    {
                        foreach (var item_ in response_.Content.Headers)
                            headers_[item_.Key] = item_.Value;
                    }

                    ProcessResponse(client_, response_);

                    var status_ = ((int)response_.StatusCode).ToString();
{%     for response in operation.Responses -%}
                    if (status_ == "{{ response.StatusCode }}"{% if response.CheckChunkedStatusCode %} || status_ == "206"{% endif %}) 
                    {
                        {% template Client.Class.ProcessResponse %}
                    }
                    else
{%     endfor -%}
{%     if operation.HasDefaultResponse -%}
{%         if operation.DefaultResponse.HasType -%}
                    {
{%             assign response = operation.DefaultResponse -%}
                        {% template Client.Class.ProcessResponse %}
                    }
{%         elseif operation.HasSuccessResponse -%}
                    {
                        var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); 
                        throw new {{ ExceptionClass }}("{{ operation.DefaultResponse.ExceptionDescription }}", (int)response_.StatusCode, responseData_, headers_, null);
                    }
{%         endif -%}
{%     else -%}
                    if (status_ != "200" && status_ != "204")
                    {
                        var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); 
                        throw new {{ ExceptionClass }}("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null);
                    }
{%     endif -%}
{%     if operation.HasDefaultResponse == false or (operation.DefaultResponse.HasType == false and operation.HasSuccessResponse == false) -%}
{%         if operation.HasResultType -%}
        
{%             if operation.WrapResponse and operation.UnwrappedResultType != "FileResponse" -%}
                    return new {{ ResponseClass }}<{{ operation.UnwrappedResultType }}>((int)response_.StatusCode, headers_, {{ operation.UnwrappedResultDefaultValue }}); 
{%             else -%}
                    return {{ operation.UnwrappedResultDefaultValue }};
{%             endif -%}
{%         elseif operation.WrapResponse -%}

                    return new {{ ResponseClass }}((int)response_.StatusCode, headers_); 
{%         endif -%}
{%     endif -%}
                }
                finally
                {
                    if (response_ != null)
                        response_.Dispose();
                }
            }
        }
        finally
        {
{%     if InjectHttpClient == false and DisposeHttpClient -%}
            if (client_ != null)
                client_.Dispose();
{%     endif -%}
        }
    }

{% endfor -%}
    protected struct ObjectResponseResult<T>
    {
        public ObjectResponseResult(T responseObject, string responseText)
        {
            this.Object = responseObject;
            this.Text = responseText;
        }

        public T Object { get; }

        public string Text { get; }
    }

    {% template Client.Class.ReadObjectResponse %}

    {% template Client.Class.ConvertToString %}
    {% template Client.Class.Body %}
}
